#include "CornerCalibrator.h"

#include <fstream> 
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <stdarg.h>

#define ESC 27
#define ENTER 10
#define SPACE 32

// рисуем целеуказатель
void CornerCalibrator :: drawTarget(IplImage* img, const int x, const int y, const int radius) const{
    cvCircle(img, cvPoint(x, y), radius, CV_RGB(250, 0, 0), 1, 8);
    cvLine(img, cvPoint(x-radius/2, y-radius/2), cvPoint(x+radius/2, y+radius/2),CV_RGB(250,0,0),1,8);
    cvLine(img, cvPoint(x-radius/2, y+radius/2), cvPoint(x+radius/2, y-radius/2),CV_RGB(250,0,0),1,8);
}

// вывод текста
void CornerCalibrator :: printText(IplImage* img, const int x, const int y, const char* text) const{
    // задаём точку для вывода текста
    CvPoint pt = cvPoint( x, y );
    // инициализация шрифта
    CvFont font;
    cvInitFont( &font, CV_FONT_HERSHEY_COMPLEX,1.0, 1.0, 0, 1, CV_AA);
    // используя шрифт выводим на картинку текст
    cvPutText(img, text, pt, &font, CV_RGB(0, 250, 0) );
}

// обработчик событий от мышки
void CornerCalibrator :: mouseClickedCorners( int x, int y ){
    printf("%d x %d\n", x, y);
    int xCenter = (topLeftX + topRightX + bottomLeftX + bottomRightX)/4;
    int yCenter = (topLeftY + topRightY + bottomLeftY + bottomRightY)/4;

    if (x < xCenter){
        if (y < yCenter){
            topLeftX = x;
            topLeftY = y;
        }else{
            bottomLeftX = x;
            bottomLeftY = y;
        }
    }else{
        if (y < yCenter){
            topRightX = x;
            topRightY = y;
        }else{
            bottomRightX = x;
            bottomRightY = y;
        }
    }
}

// обработчик событий от мышки
void myMouseCallbackCorners( int event, int x, int y, int flags, void* param ){
    CornerCalibrator* c = (CornerCalibrator*) param;
    switch( event ){
        case CV_EVENT_MOUSEMOVE: 
            break;

        case CV_EVENT_LBUTTONDOWN:
            c->mouseClickedCorners(x, y);
            break;

        case CV_EVENT_LBUTTONUP:
            break;
    }
}

void CornerCalibrator :: getCorners(){
    cvNamedWindow("calibrateCorners", CV_WINDOW_AUTOSIZE);
    cvMoveWindow("calibrateCorners", 0, 0);

    bool ifHaveCorners = false;

    IplImage* img = cvCreateImage( cvGetSize(calibrationImage), IPL_DEPTH_8U, 3 );

    topLeftX = 81;
    topLeftY = 66;
    topRightX = 462;
    topRightY = 58;
    bottomLeftX = 70;
    bottomLeftY = 441;
    bottomRightX = 494;
    bottomRightY = 406;

    while(!ifHaveCorners){
        // копируем изображение
        cvCopyImage(calibrationImage, img);
        int height    = img->height;
        int width     = img->width;
        printText (img, height/4, width*2/10, "Click at all corners.");
        printText (img, height/4, width*3/10, "Press esc after all.");

        drawTarget (img, topLeftX, topLeftY, 10);
        drawTarget (img, topRightX, topRightY, 10);
        drawTarget (img, bottomLeftX, bottomLeftY, 10);
        drawTarget (img, bottomRightX, bottomRightY, 10);

        cvShowImage( "calibrateCorners", img );
        // вешаем обработчик мышки
        cvSetMouseCallback( "calibrateCorners", myMouseCallbackCorners, this);

        char c = cvWaitKey(33);
        if (c == ESC) {
            ifHaveCorners = true;
            break;
        }
    }

    cvDestroyWindow("calibrateCorners");

    cvReleaseImage(&img);
}

CornerCalibrator::CornerCalibrator(IplImage* img){
    calibrationImage = cvCreateImage( cvGetSize(img), IPL_DEPTH_8U, 3 );
    // копируем изображение
    cvCopyImage(img, calibrationImage);
    getCorners();
}

CornerCalibrator::~CornerCalibrator(){
    cvDestroyAllWindows();
}

void CornerCalibrator::getParams (int* tlX, int* tlY, int* trX, int* trY, int* blX, int* blY, int* brX, int* brY) const{
    *tlX = topLeftX;
    *tlY = topLeftY;
    *trX = topRightX;
    *trY = topRightY;
    *blX = bottomLeftX;
    *blY = bottomLeftY;
    *brX = bottomRightX;
    *brY = bottomRightY;
}

